package com.laker.autotest.desktop;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;

import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.io.File;
import java.util.List;

public class ScriptService {
    private static final String SCRIPT_FILE = "recorded_script.json";
    private final EventListModel eventListModel;

    public ScriptService(EventListModel eventListModel) {
        this.eventListModel = eventListModel;
    }

    public void saveScript(List<ScriptEvent> scriptEvents) {
        try {
            JSONArray arr = new JSONArray();
            for (ScriptEvent event : scriptEvents) {
                arr.add(new JSONObject(event));
            }
            FileUtil.writeUtf8String(arr.toStringPretty(), System.getProperty("user.dir") + File.separator + SCRIPT_FILE);
            eventListModel.addElement("[脚本已保存] " + System.getProperty("user.dir") + File.separator + SCRIPT_FILE);
        } catch (Exception e) {
            eventListModel.addElement("[保存失败] " + e.getMessage());
        }
    }

    public void playbackScript() {
        new Thread(() -> {
            try {
                String json = FileUtil.readUtf8String(System.getProperty("user.dir") + File.separator + SCRIPT_FILE);
                JSONArray arr = JSONUtil.parseArray(json);
                SwingUtilities.invokeLater(() -> eventListModel.addElement("[开始回放]"));
                Robot robot = new Robot();
                long lastTimestamp = -1;
                for (Object obj : arr) {
                    ScriptEvent event;
                    if (obj instanceof JSONObject) {
                        JSONObject jo = (JSONObject) obj;
                        event = jo.toBean(ScriptEvent.class);
                        if (event.getType() == null && jo.containsKey("type")) {
                            Object typeObj = jo.get("type");
                            if (typeObj instanceof String) {
                                event.setType((String) typeObj);
                            } else if (typeObj instanceof Integer) {
                                EventType[] types = EventType.values();
                                int ordinal = (Integer) typeObj;
                                if (ordinal >= 0 && ordinal < types.length) {
                                    event.setType(types[ordinal].name());
                                }
                            }
                        }
                    } else {
                        event = new ScriptEvent();
                    }
                    if (event.getType() == null) {
                        SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 跳过未知事件"));
                        lastTimestamp = event.getTimestamp();
                        continue;
                    }
                    if (lastTimestamp > 0) {
                        long interval = event.getTimestamp() - lastTimestamp;
                        if (interval > 0 && interval < 10000) {
                            Thread.sleep(interval);
                        }
                    }
                    lastTimestamp = event.getTimestamp();
                    try {
                        switch (event.getType()) {
                            case KEY_PRESS:
                                KeyEvent pressKeyEvent = event.getKeyEvent();
                                if (pressKeyEvent != null) {
                                    NativeKeyEvent keyEvent = new NativeKeyEvent(
                                            pressKeyEvent.getId(),
                                            pressKeyEvent.getModifiers(),
                                            pressKeyEvent.getRawCode(),
                                            pressKeyEvent.getKeyCode(),
                                            pressKeyEvent.getKeyChar(),
                                            pressKeyEvent.getKeyLocation()
                                    );
                                    GlobalScreen.postNativeEvent(keyEvent);
                                    SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 按键按下: " + NativeKeyEvent.getKeyText(event.getKeyEvent().getKeyCode())));
                                }
                                break;
                            case KEY_RELEASE:
                                KeyEvent releaseKeyEvent = event.getKeyEvent();
                                if (releaseKeyEvent != null) {
                                    NativeKeyEvent keyEvent = new NativeKeyEvent(
                                            releaseKeyEvent.getId(),
                                            releaseKeyEvent.getModifiers(),
                                            releaseKeyEvent.getRawCode(),
                                            releaseKeyEvent.getKeyCode(),
                                            releaseKeyEvent.getKeyChar(),
                                            releaseKeyEvent.getKeyLocation()
                                    );
                                    GlobalScreen.postNativeEvent(keyEvent);
                                    SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 按键释放: " + NativeKeyEvent.getKeyText(event.getKeyEvent().getKeyCode())));
                                }
                                break;
                            case KEY_TYPED:
                                KeyEvent typedKeyEvent = event.getKeyEvent();
                                if (typedKeyEvent != null) {
                                    NativeKeyEvent keyEvent = new NativeKeyEvent(
                                            typedKeyEvent.getId(),
                                            typedKeyEvent.getModifiers(),
                                            typedKeyEvent.getRawCode(),
                                            typedKeyEvent.getKeyCode(),
                                            typedKeyEvent.getKeyChar(),
                                            typedKeyEvent.getKeyLocation()
                                    );
                                    GlobalScreen.postNativeEvent(keyEvent);
                                    SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 按键输入: " + typedKeyEvent.getKeyChar()));
                                }
                                break;
                            case MOUSE_MOVE:
                                robot.mouseMove(event.getX(), event.getY());
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 鼠标移动: (" + event.getX() + ", " + event.getY() + ")"));
                                break;
                            case MOUSE_CLICK:
                                robot.mouseMove(event.getX(), event.getY());
                                int btn = event.getButton() == 1 ? InputEvent.BUTTON1_DOWN_MASK : InputEvent.BUTTON3_DOWN_MASK;
                                robot.mousePress(btn);
                                robot.mouseRelease(btn);
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 鼠标点击: " + event.getButton() + " at (" + event.getX() + ", " + event.getY() + ")"));
                                break;
                            case MOUSE_PRESS:
                                robot.mouseMove(event.getX(), event.getY());
                                int pressBtn = event.getButton() == 1 ? InputEvent.BUTTON1_DOWN_MASK : InputEvent.BUTTON3_DOWN_MASK;
                                robot.mousePress(pressBtn);
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 鼠标按下: " + event.getButton() + " at (" + event.getX() + ", " + event.getY() + ")"));
                                break;
                            case MOUSE_RELEASE:
                                robot.mouseMove(event.getX(), event.getY());
                                int releaseBtn = event.getButton() == 1 ? InputEvent.BUTTON1_DOWN_MASK : InputEvent.BUTTON3_DOWN_MASK;
                                robot.mouseRelease(releaseBtn);
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 鼠标释放: " + event.getButton() + " at (" + event.getX() + ", " + event.getY() + ")"));
                                break;
                            case MOUSE_DRAG:
                                robot.mouseMove(event.getX(), event.getY());
                                robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                                robot.mouseMove(event.getX2(), event.getY2());
                                robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 鼠标拖动: (" + event.getX() + ", " + event.getY() + ") -> (" + event.getX2() + ", " + event.getY2() + ")"));
                                break;
                            case MOUSE_WHEEL:
                                robot.mouseWheel(event.getWheelRotation() != null ? event.getWheelRotation() : 0);
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 鼠标滚轮: " + event.getWheelRotation()));
                                break;
                            case SCREENSHOT:
                                // 截图事件暂不支持回放，可在此处扩展
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 截图事件: " + event.getImagePath() + " 区域: " + event.getRegion()));
                                break;
                            case SCROLL:
                                // 滚动事件暂不支持回放，可在此处扩展
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 滚动事件: (" + event.getX() + ", " + event.getY() + ") -> (" + event.getX2() + ", " + event.getY2() + ")"));
                                break;
                            default:
                                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 未知事件"));
                        }
                    } catch (Exception ex) {
                        SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放] 事件反序列化失败: " + ex.getMessage()));
                    }
                }
                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放结束]"));
            } catch (Exception e) {
                SwingUtilities.invokeLater(() -> eventListModel.addElement("[回放失败] " + e.getMessage()));
            }
        }).start();
    }
}
